home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo2.zoo / demo / ex / ex_voper.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  14.7 KB  |  865 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *sccsid = "@(#)ex_voper.c    7.5 (Berkeley) 3/9/87; 1.2 (Bellcore)    87/04/24";
  9. #endif not lint
  10.  
  11. #include "ex.h"
  12. #include "ex_tty.h"
  13. #include "ex_vis.h"
  14.  
  15. #define    blank()        isspace(wcursor[0])
  16. #define    forbid(a)    if (a) goto errlab;
  17.  
  18. char    vscandir[2] =    { '/', 0 };
  19.  
  20. /*
  21.  * Decode an operator/operand type command.
  22.  * Eventually we switch to an operator subroutine in ex_vops.c.
  23.  * The work here is setting up a function variable to point
  24.  * to the routine we want, and manipulation of the variables
  25.  * wcursor and wdot, which mark the other end of the affected
  26.  * area.  If wdot is zero, then the current line is the other end,
  27.  * and if wcursor is zero, then the first non-blank location of the
  28.  * other line is implied.
  29.  */
  30. operate(c, cnt)
  31.     register int c, cnt;
  32. {
  33.     register int i;
  34.     int (*moveop)(), (*deleteop)();
  35.     register int (*opf)();
  36.     bool subop = 0;
  37.     char *oglobp, *ocurs;
  38.     register line *addr;
  39.     line *odot;
  40.     static char lastFKND, lastFCHR;
  41.     short d;
  42.  
  43.     moveop = vmove, deleteop = vdelete;
  44.     wcursor = cursor;
  45.     wdot = NOLINE;
  46.     notecnt = 0;
  47.     dir = 1;
  48.     switch (c) {
  49.  
  50.     /*
  51.      * d        delete operator.
  52.      */
  53.     case 'd':
  54.         moveop = vdelete;
  55.         deleteop = beep;
  56.         break;
  57.  
  58.     /*
  59.      * s        substitute characters, like c\040, i.e. change space.
  60.      */
  61.     case 's':
  62.         ungetkey(' ');
  63.         subop++;
  64.         /* fall into ... */
  65.  
  66.     /*
  67.      * c        Change operator.
  68.      */
  69.     case 'c':
  70.         if (c == 'c' && workcmd[0] == 'C' || workcmd[0] == 'S')
  71.             subop++;
  72.         moveop = vchange;
  73.         deleteop = beep;
  74.         break;
  75.  
  76.     /*
  77.      * !        Filter through a UNIX command.
  78.      */
  79.     case '!':
  80.         moveop = vfilter;
  81.         deleteop = beep;
  82.         break;
  83.  
  84.     /*
  85.      * y        Yank operator.  Place specified text so that it
  86.      *        can be put back with p/P.  Also yanks to named buffers.
  87.      */
  88.     case 'y':
  89.         moveop = vyankit;
  90.         deleteop = beep;
  91.         break;
  92.  
  93.     /*
  94.      * =        Reformat operator (for LISP).
  95.      */
  96. #ifdef LISPCODE
  97.     case '=':
  98.         forbid(!value(LISP));
  99.         /* fall into ... */
  100. #endif
  101.  
  102.     /*
  103.      * >        Right shift operator.
  104.      * <        Left shift operator.
  105.      */
  106.     case '<':
  107.     case '>':
  108.         moveop = vshftop;
  109.         deleteop = beep;
  110.         break;
  111.  
  112.     /*
  113.      * r        Replace character under cursor with single following
  114.      *        character.
  115.      */
  116.     case 'r':
  117.         vmacchng(1);
  118.         vrep(cnt);
  119.         return;
  120.  
  121.     default:
  122.         goto nocount;
  123.     }
  124.     vmacchng(1);
  125.     /*
  126.      * Had an operator, so accept another count.
  127.      * Multiply counts together.
  128.      */
  129.     if (isdigit(peekkey()) && peekkey() != '0') {
  130.         cnt *= vgetcnt();
  131.         Xcnt = cnt;
  132.         forbid (cnt <= 0);
  133.     }
  134.  
  135.     /*
  136.      * Get next character, mapping it and saving as
  137.      * part of command for repeat.
  138.      */
  139.     c = map(getesc(),arrows);
  140.     if (c == 0)
  141.         return;
  142.     if (!subop)
  143.         *lastcp++ = c;
  144. nocount:
  145.     opf = moveop;
  146.     switch (c) {
  147.  
  148.     /*
  149.      * b        Back up a word.
  150.      * B        Back up a word, liberal definition.
  151.      */
  152.     case 'b':
  153.     case 'B':
  154.         dir = -1;
  155.         /* fall into ... */
  156.  
  157.     /*
  158.      * w        Forward a word.
  159.      * W        Forward a word, liberal definition.
  160.      */
  161.     case 'W':
  162.     case 'w':
  163.         wdkind = c & ' ';
  164.         forbid(lfind(2, cnt, opf, (line *) 0) < 0);
  165.         vmoving = 0;
  166.         break;
  167.  
  168.     /*
  169.      * E        to end of following blank/nonblank word
  170.      */
  171.     case 'E':
  172.         wdkind = 0;
  173.         goto ein;
  174.  
  175.     /*
  176.      * e        To end of following word.
  177.      */
  178.     case 'e':
  179.         wdkind = 1;
  180. ein:
  181.         forbid(lfind(3, cnt - 1, opf, (line *) 0) < 0);
  182.         vmoving = 0;
  183.         break;
  184.  
  185.     /*
  186.      * (        Back an s-expression.
  187.      */
  188.     case '(':
  189.         dir = -1;
  190.         /* fall into... */
  191.  
  192.     /*
  193.      * )        Forward an s-expression.
  194.      */
  195.     case ')':
  196.         forbid(lfind(0, cnt, opf, (line *) 0) < 0);
  197.         markDOT();
  198.         break;
  199.  
  200.     /*
  201.      * {        Back an s-expression, but don't stop on atoms.
  202.      *        In text mode, a paragraph.  For C, a balanced set
  203.      *        of {}'s.
  204.      */
  205.     case '{':
  206.         dir = -1;
  207.         /* fall into... */
  208.  
  209.     /*
  210.      * }        Forward an s-expression, but don't stop on atoms.
  211.      *        In text mode, back paragraph.  For C, back a balanced
  212.      *        set of {}'s.
  213.      */
  214.     case '}':
  215.         forbid(lfind(1, cnt, opf, (line *) 0) < 0);
  216.         markDOT();
  217.         break;
  218.  
  219.     /*
  220.      * %        To matching () or {}.  If not at ( or { scan for
  221.      *        first such after cursor on this line.
  222.      */
  223.     case '%':
  224.         vsave();
  225.         i = lmatchp((line *) 0);
  226. #ifdef TRACE
  227.         if (trace)
  228.             fprintf(trace, "after lmatchp in %, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol));
  229. #endif
  230.         getDOT();
  231.         forbid(!i);
  232.         if (opf != vmove)
  233.             if (dir > 0)
  234.                 wcursor++;
  235.             else
  236.                 cursor++;
  237.         else
  238.             markDOT();
  239.         vmoving = 0;
  240.         break;
  241.  
  242.     /*
  243.      * [        Back to beginning of defun, i.e. an ( in column 1.
  244.      *        For text, back to a section macro.
  245.      *        For C, back to a { in column 1 (~~ beg of function.)
  246.      */
  247.     case '[':
  248.         dir = -1;
  249.         /* fall into ... */
  250.  
  251.     /*
  252.      * ]        Forward to next defun, i.e. a ( in column 1.
  253.      *        For text, forward section.
  254.      *        For C, forward to a } in column 1 (if delete or such)
  255.      *        or if a move to a { in column 1.
  256.      */
  257.     case ']':
  258.         if (!vglobp)
  259.             forbid(getkey() != c);
  260.         forbid (Xhadcnt);
  261.         vsave();
  262.         i = lbrack(c, opf);
  263.         getDOT();
  264.         forbid(!i);
  265.         markDOT();
  266.         if (ospeed > B300)
  267.             hold |= HOLDWIG;
  268.         break;
  269.  
  270.     /*
  271.      * ,        Invert last find with f F t or T, like inverse
  272.      *        of ;.
  273.      */
  274.     case ',':
  275.         forbid (lastFKND == 0);
  276.         c = isupper(lastFKND) ? tolower(lastFKND) : toupper(lastFKND);
  277.         i = lastFCHR;
  278.         if (vglobp == 0)
  279.             vglobp = "";
  280.         subop++;
  281.         goto nocount;
  282.  
  283.     /*
  284.      * 0        To beginning of real line.
  285.      */
  286.     case '0':
  287.         wcursor = linebuf;
  288.         vmoving = 0;
  289.         break;
  290.  
  291.     /*
  292.      * ;        Repeat last find with f F t or T.
  293.      */
  294.     case ';':
  295.         forbid (lastFKND == 0);
  296.         c = lastFKND;
  297.         i = lastFCHR;
  298.         subop++;
  299.         goto nocount;
  300.  
  301.     /*
  302.      * F        Find single character before cursor in current line.
  303.      * T        Like F, but stops before character.
  304.      */
  305.     case 'F':    /* inverted find */
  306.     case 'T':
  307.         dir = -1;
  308.         /* fall into ... */
  309.  
  310.     /*
  311.      * f        Find single character following cursor in current line.
  312.      * t        Like f, but stope before character.
  313.      */
  314.     case 'f':    /* find */
  315.     case 't':
  316.         if (!subop) {
  317.             i = getesc();
  318.             if (i == 0)
  319.                 return;
  320.             *lastcp++ = i;
  321.         }
  322.         if (vglobp == 0)
  323.             lastFKND = c, lastFCHR = i;
  324.         for (; cnt > 0; cnt--)
  325.             forbid (find(i) == 0);
  326.         vmoving = 0;
  327.         switch (c) {
  328.  
  329.         case 'T':
  330.             wcursor++;
  331.             break;
  332.  
  333.         case 't':
  334.             wcursor--;
  335.         case 'f':
  336. fixup:
  337.             if (moveop != vmove)
  338.                 wcursor++;
  339.             break;
  340.         }
  341.         break;
  342.  
  343.     /*
  344.      * |        Find specified print column in current line.
  345.      */
  346.     case '|':
  347.         if (Pline == numbline)
  348.             cnt += 8;
  349.         vmovcol = cnt;
  350.         vmoving = 1;
  351.         wcursor = vfindcol(cnt);
  352.         break;
  353.  
  354.     /*
  355.      * ^        To beginning of non-white space on line.
  356.      */
  357.     case '^':
  358.         wcursor = vskipwh(linebuf);
  359.         vmoving = 0;
  360.         break;
  361.  
  362.     /*
  363.      * $        To end of line.
  364.      */
  365.     case '$':
  366.         if (opf == vmove) {
  367.             vmoving = 1;
  368.             vmovcol = 20000;
  369.         } else
  370.             vmoving = 0;
  371.         if (cnt > 1) {
  372.             if (opf == vmove) {
  373.                 wcursor = 0;
  374.                 cnt--;
  375.             } else
  376.                 wcursor = linebuf;
  377.             /* This is wrong at EOF */
  378.             wdot = dot + cnt;
  379.             break;
  380.         }
  381.         if (linebuf[0]) {
  382.             wcursor = strend(linebuf) - 1;
  383.             goto fixup;
  384.         }
  385.         wcursor = linebuf;
  386.         break;
  387.  
  388.     /*
  389.      * h        Back a character.
  390.      * ^H        Back a character.
  391.      */
  392.     case 'h':
  393.     case CTRL(h):
  394.         dir = -1;
  395.         /* fall into ... */
  396.  
  397.     /*
  398.      * space    Forward a character.
  399.      */
  400.     case 'l':
  401.     case ' ':
  402.         forbid (margin() || opf == vmove && edge());
  403.         while (cnt > 0 && !margin())
  404.             wcursor += dir, cnt--;
  405.         if (margin() && opf == vmove || wcursor < linebuf)
  406.             wcursor -= dir;
  407.         vmoving = 0;
  408.         break;
  409.  
  410.     /*
  411.      * D        Delete to end of line, short for d$.
  412.      */
  413.     case 'D':
  414.         cnt = INF;
  415.         goto deleteit;
  416.  
  417.     /*
  418.      * X        Delete character before cursor.
  419.      */
  420.     case 'X':
  421.         dir = -1;
  422.         /* fall into ... */
  423. deleteit:
  424.     /*
  425.      * x        Delete character at cursor, leaving cursor where it is.
  426.      */
  427.     case 'x':
  428.         if (margin())
  429.             goto errlab;
  430.         vmacchng(1);
  431.         while (cnt > 0 && !margin())
  432.             wcursor += dir, cnt--;
  433.         opf = deleteop;
  434.         vmoving = 0;
  435.         break;
  436.  
  437.     default:
  438.         /*
  439.          * Stuttered operators are equivalent to the operator on
  440.          * a line, thus turn dd into d_.
  441.          */
  442.         if (opf == vmove || c != workcmd[0]) {
  443. errlab:
  444.             beep();
  445.             vmacp = 0;
  446.             return;
  447.         }
  448.         /* fall into ... */
  449.  
  450.     /*
  451.      * _        Target for a line or group of lines.
  452.      *        Stuttering is more convenient; this is mostly
  453.      *        for aesthetics.
  454.      */
  455.     case '_':
  456.         wdot = dot + cnt - 1;
  457.         vmoving = 0;
  458.         wcursor = 0;
  459.         break;
  460.  
  461.     /*
  462.      * H        To first, home line on screen.
  463.      *        Count is for count'th line rather than first.
  464.      */
  465.     case 'H':
  466.         wdot = (dot - vcline) + cnt - 1;
  467.         if (opf == vmove)
  468.             markit(wdot);
  469.         vmoving = 0;
  470.         wcursor = 0;
  471.         break;
  472.  
  473.     /*
  474.      * -        Backwards lines, to first non-white character.
  475.      */
  476.     case '-':
  477.         wdot = dot - cnt;
  478.         vmoving = 0;
  479.         wcursor = 0;
  480.         break;
  481.  
  482.     /*
  483.      * ^P        To previous line same column.  Ridiculous on the
  484.      *        console of the VAX since it puts console in LSI mode.
  485.      */
  486.     case 'k':
  487.     case CTRL(p):
  488.         wdot = dot - cnt;
  489.         if (vmoving == 0)
  490.             vmoving = 1, vmovcol = column(cursor);
  491.         wcursor = 0;
  492.         break;
  493.  
  494.     /*
  495.      * L        To last line on screen, or count'th line from the
  496.      *        bottom.
  497.      */
  498.     case 'L':
  499.         wdot = dot + vcnt - vcline - cnt;
  500.         if (opf == vmove)
  501.             markit(wdot);
  502.         vmoving = 0;
  503.         wcursor = 0;
  504.         break;
  505.  
  506.     /*
  507.      * M        To the middle of the screen.
  508.      */
  509.     case 'M':
  510.         wdot = dot + ((vcnt + 1) / 2) - vcline - 1;
  511.         if (opf == vmove)
  512.             markit(wdot);
  513.         vmoving = 0;
  514.         wcursor = 0;
  515.         break;
  516.  
  517.     /*
  518.      * +        Forward line, to first non-white.
  519.      *
  520.      * CR        Convenient synonym for +.
  521.      */
  522.     case '+':
  523.     case CR:
  524.         wdot = dot + cnt;
  525.         vmoving = 0;
  526.         wcursor = 0;
  527.         break;
  528.  
  529.     /*
  530.      * ^N        To next line, same column if possible.
  531.      *
  532.      * LF        Linefeed is a convenient synonym for ^N.
  533.      */
  534.     case CTRL(n):
  535.     case 'j':
  536.     case NL:
  537.         wdot = dot + cnt;
  538.         if (vmoving == 0)
  539.             vmoving = 1, vmovcol = column(cursor);
  540.         wcursor = 0;
  541.         break;
  542.  
  543.     /*
  544.      * n        Search to next match of current pattern.
  545.      */
  546.     case 'n':
  547.         vglobp = vscandir;
  548.         c = *vglobp++;
  549.         goto nocount;
  550.  
  551.     /*
  552.      * N        Like n but in reverse direction.
  553.      */
  554.     case 'N':
  555.         vglobp = vscandir[0] == '/' ? "?" : "/";
  556.         c = *vglobp++;
  557.         goto nocount;
  558.  
  559.     /*
  560.      * '        Return to line specified by following mark,
  561.      *        first white position on line.
  562.      *
  563.      * `        Return to marked line at remembered column.
  564.      */
  565.     case '\'':
  566.     case '`':
  567.         d = c;
  568.         c = getesc();
  569.         if (c == 0)
  570.             return;
  571.         c = markreg(c);
  572.         forbid (c == 0);
  573.         wdot = getmark(c);
  574.         forbid (wdot == NOLINE);
  575.         forbid (Xhadcnt);
  576.         vmoving = 0;
  577.         wcursor = d == '`' ? ncols[c - 'a'] : 0;
  578.         if (opf == vmove && (wdot != dot || (d == '`' && wcursor != cursor)))
  579.             markDOT();
  580.         if (wcursor) {
  581.             vsave();
  582.             getline(*wdot);
  583.             if (wcursor > strend(linebuf))
  584.                 wcursor = 0;
  585.             getDOT();
  586.         }
  587.         if (ospeed > B300)
  588.             hold |= HOLDWIG;
  589.         break;
  590.  
  591.     /*
  592.      * G        Goto count'th line, or last line if no count
  593.      *        given.
  594.      */
  595.     case 'G':
  596.         if (!Xhadcnt)
  597.             cnt = lineDOL();
  598.         wdot = zero + cnt;
  599.         forbid (wdot < one || wdot > dol);
  600.         if (opf == vmove)
  601.             markit(wdot);
  602.         vmoving = 0;
  603.         wcursor = 0;
  604.         break;
  605.  
  606.     /*
  607.      * /        Scan forward for following re.
  608.      * ?        Scan backward for following re.
  609.      */
  610.     case '/':
  611.     case '?':
  612.         forbid (Xhadcnt);
  613.         vsave();
  614.         ocurs = cursor;
  615.         odot = dot;
  616.         wcursor = 0;
  617.         if (readecho(c))
  618.             return;
  619.         if (!vglobp)
  620.             vscandir[0] = genbuf[0];
  621.         oglobp = globp; CP(vutmp, genbuf); globp = vutmp;
  622.         d = peekc;
  623. fromsemi:
  624.         ungetchar(0);
  625.         fixech();
  626.         CATCH
  627. #ifndef CBREAK
  628.             /*
  629.              * Lose typeahead (ick).
  630.              */
  631.             vcook();
  632. #endif
  633.             addr = address(cursor);
  634. #ifndef CBREAK
  635.             vraw();
  636. #endif
  637.         ONERR
  638. #ifndef CBREAK
  639.             vraw();
  640. #endif
  641. slerr:
  642.             globp = oglobp;
  643.             dot = odot;
  644.             cursor = ocurs;
  645.             ungetchar(d);
  646.             splitw = 0;
  647.             vclean();
  648.             vjumpto(dot, ocurs, 0);
  649.             return;
  650.         ENDCATCH
  651.         if (globp == 0)
  652.             globp = "";
  653.         else if (peekc)
  654.             --globp;
  655.         if (*globp == ';') {
  656.             /* /foo/;/bar/ */
  657.             globp++;
  658.             dot = addr;
  659.             cursor = loc1;
  660.             goto fromsemi;
  661.         }
  662.         dot = odot;
  663.         ungetchar(d);
  664.         c = 0;
  665.         if (*globp == 'z')
  666.             globp++, c = '\n';
  667.         if (any(*globp, "^+-."))
  668.             c = *globp++;
  669.         i = 0;
  670.         while (isdigit(*globp))
  671.             i = i * 10 + *globp++ - '0';
  672.         if (any(*globp, "^+-."))
  673.             c = *globp++;
  674.         if (*globp) {
  675.             /* random junk after the pattern */
  676.             beep();
  677.             goto slerr;
  678.         }
  679.         globp = oglobp;
  680.         splitw = 0;
  681.         vmoving = 0;
  682.         wcursor = loc1;
  683.         if (i != 0)
  684.             vsetsiz(i);
  685.         if (opf == vmove) {
  686.             if (state == ONEOPEN || state == HARDOPEN)
  687.                 outline = destline = WBOT;
  688.             if (addr != dot || loc1 != cursor)
  689.                 markDOT();
  690.             if (loc1 > linebuf && *loc1 == 0)
  691.                 loc1--;
  692.             if (c)
  693.                 vjumpto(addr, loc1, c);
  694.             else {
  695.                 vmoving = 0;
  696.                 if (loc1) {
  697.                     vmoving++;
  698.                     vmovcol = column(loc1);
  699.                 }
  700.                 getDOT();
  701.                 if (state == CRTOPEN && addr != dot)
  702.                     vup1();
  703.                 vupdown(addr - dot, NOSTR);
  704.             }
  705.             return;
  706.         }
  707.         lastcp[-1] = 'n';
  708.         getDOT();
  709.         wdot = addr;
  710.         break;
  711.     }
  712.     /*
  713.      * Apply.
  714.      */
  715.     if (vreg && wdot == 0)
  716.         wdot = dot;
  717.     (*opf)(c);
  718. flusho();
  719.     wdot = NOLINE;
  720. }
  721.  
  722. /*
  723.  * Find single character c, in direction dir from cursor.
  724.  */
  725. find(c)
  726.     char c;
  727. {
  728.  
  729.     for(;;) {
  730.         if (edge())
  731.             return (0);
  732.         wcursor += dir;
  733.         if (*wcursor == c)
  734.             return (1);
  735.     }
  736. }
  737.  
  738. /*
  739.  * Do a word motion with operator op, and cnt more words
  740.  * to go after this.
  741.  */
  742. word(op, cnt)
  743.     register int (*op)();
  744.     int cnt;
  745. {
  746.     register int which;
  747.     register char *iwc;
  748.     register line *iwdot = wdot;
  749.  
  750.     if (dir == 1) {
  751.         iwc = wcursor;
  752.         which = wordch(wcursor);
  753.         while (wordof(which, wcursor)) {
  754.             if (cnt == 1 && op != vmove && wcursor[1] == 0) {
  755.                 wcursor++;
  756.                 break;
  757.             }
  758.             if (!lnext())
  759.                 return (0);
  760.             if (wcursor == linebuf)
  761.                 break;
  762.         }
  763.         /* Unless last segment of a change skip blanks */
  764.         if (op != vchange || cnt > 1)
  765.             while (!margin() && blank())
  766.                 wcursor++;
  767.         else
  768.             if (wcursor == iwc && iwdot == wdot && *iwc)
  769.                 wcursor++;
  770.         if (op == vmove && margin())
  771.             wcursor--;
  772.     } else {
  773.         if (!lnext())
  774.             return (0);
  775.         while (blank())
  776.             if (!lnext())
  777.                 return (0);
  778.         if (!margin()) {
  779.             which = wordch(wcursor);
  780.             while (!margin() && wordof(which, wcursor))
  781.                 wcursor--;
  782.         }
  783.         if (wcursor < linebuf || !wordof(which, wcursor))
  784.             wcursor++;
  785.     }
  786.     return (1);
  787. }
  788.  
  789. /*
  790.  * To end of word, with operator op and cnt more motions
  791.  * remaining after this.
  792.  */
  793. eend(op)
  794.     register int (*op)();
  795. {
  796.     register int which;
  797.  
  798.     if (!lnext())
  799.         return;
  800.     while (blank())
  801.         if (!lnext())
  802.             return;
  803.     which = wordch(wcursor);
  804.     while (wordof(which, wcursor)) {
  805.         if (wcursor[1] == 0) {
  806.             wcursor++;
  807.             break;
  808.         }
  809.         if (!lnext())
  810.             return;
  811.     }
  812.     if (op != vchange && op != vdelete && wcursor > linebuf)
  813.         wcursor--;
  814. }
  815.  
  816. /*
  817.  * Wordof tells whether the character at *wc is in a word of
  818.  * kind which (blank/nonblank words are 0, conservative words 1).
  819.  */
  820. wordof(which, wc)
  821.     char which;
  822.     register char *wc;
  823. {
  824.  
  825.     if (isspace(*wc))
  826.         return (0);
  827.     return (!wdkind || wordch(wc) == which);
  828. }
  829.  
  830. /*
  831.  * Wordch tells whether character at *wc is a word character
  832.  * i.e. an alfa, digit, or underscore.
  833.  */
  834. wordch(wc)
  835.     char *wc;
  836. {
  837.     register int c;
  838.  
  839.     c = wc[0];
  840.     return (isalpha(c) || isdigit(c) || c == '_');
  841. }
  842.  
  843. /*
  844.  * Edge tells when we hit the last character in the current line.
  845.  */
  846. edge()
  847. {
  848.  
  849.     if (linebuf[0] == 0)
  850.         return (1);
  851.     if (dir == 1)
  852.         return (wcursor[1] == 0);
  853.     else
  854.         return (wcursor == linebuf);
  855. }
  856.  
  857. /*
  858.  * Margin tells us when we have fallen off the end of the line.
  859.  */
  860. margin()
  861. {
  862.  
  863.     return (wcursor < linebuf || wcursor[0] == 0);
  864. }
  865.